#include <algorithm>
#include <cmath>
#include <fstream>
#include <vector>

#include "predicates.h"

std::ifstream in ("in.txt");
std::ofstream out("out.txt");

struct border
{
	int up;
	int low;
	border ()
	{
		up = -INF;
		low = INF;
	}
};

int get_segment_sign(const point &a, const point &b)
{
	if ((b.y - a.y) > 0)
	{
		return 1;
	}
	if ((b.y - a.y) < 0)
	{
		return -1;
	}
	return 0;
};

std::vector<point> rasterization(point &a, point &b)
{
	if (a.x > b.x)
	{
		std::swap(a,b);
	}
	std::vector <point> result;
	point curent(floor(a.x),floor(a.y));
	point up_border(floor(b.x),floor(b.y));
	int sign = get_segment_sign(a, b);
	result.push_back(curent);
	while (curent !=  up_border)
	{
		point temp = curent;
		temp.x++;
		if (sign > 0)
		{
			temp.y++;
		}
		int left_turn_result = left_turn(a, b, temp);
		if (sign == 1)
		{
			if (left_turn_result == 1)
			{
				curent.x++;
			}
			else if (left_turn_result == 0)
			{
				curent.x++;
				curent.y++;
			}
			else if (left_turn_result == -1)
			{
				curent.y++;
			}
		}
		else if (sign == -1)
		{
			if (left_turn_result == 1)
			{
				curent.y--;
			}
			else if (left_turn_result == 0)
			{
				result.push_back(curent);
				curent.x++;
				curent.y--;
			}
			else if (left_turn_result == -1)
			{
				curent.x++;

			}
		}
		else if (sign == 0)
		{
			curent.x++;
			if (curent.x > up_border.x)
			{
				break;
			}
		}
		if ((sign != 0) && (curent.x == up_border.x) && ((curent.y - up_border.y) * sign > 0))
		{
			break;
		}
		result.push_back(curent);
	}
	return result;
}

void generate_border(point a, point b, std::vector<border> &res, int min_x)
{
	std::vector<point> r = rasterization(a, b);
	for (size_t i = 0; i < r.size(); i++)
	{
		res[r[i].x - min_x].low = std::min(res[r[i].x - min_x].low, static_cast<int> (r[i].y));
		res[r[i].x - min_x].up = std::max(res[r[i].x - min_x].up, static_cast<int> (r[i].y));
	}
}

long long solve(std::vector<point> &p, std::vector <border> &res, int min_x)
{
	for (size_t i = 0; i < p.size(); i++)
	{
		generate_border(p[i], p[(i + 1) % p.size()], res, min_x);
	}
	long long ans = 0;
    for (size_t i = 0; i < res.size(); i++)
    {
		ans += res[i].up - res[i].low + 1;
    }
	return ans;
}

int main()
{
	int n;
	in >> n;
	std::vector <point> points(n);
	for (size_t i = 0; i < n; i++)
	{
		in >> points[i].x >> points[i].y;
	}
	auto min_max = std::minmax_element(points.begin(), points.end(), points_x_predicate);
	int min_x = min_max.first -> x;
	int max_x = min_max.second -> x;
	std::vector <border> answer (max_x - min_x + 1);
	long long ans = solve(points, answer, min_x);
	out << ans << '\n';
	for (int x = min_x; x <= max_x; x++)
	{
		for (int y = answer[x - min_x].low; y <= answer[x - min_x].up; y++)
        {
			out << x << " " << y << "\n";
		}
	}
}